﻿using NewsMine.DataManagers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.IO;
using NewsMine.Storage;
using NewsMine.DomainObjects;
using System.Net.Mail;
using System.Net;
using NewsMine.Utilities;
using NewsMine.DataManagers;
using System.Drawing.Imaging;
using System.Xml.Linq;
using Facebook;
using System.Dynamic;

namespace Winapp.NewsMine.FacebookAutoPoster
{
    public partial class FrmPictureGenerator : Form
    {
        internal class IntermideateDataForFacebookPost
        {
            public FaceBookEmailPostData FaceBookEmailPostData { get; set; }
            public string HtmlContent { get; set; }
            public string GeneratePicturePath { get; set; }
            public string GeneratedHtmlFilePath { get; set; }
        }

        static Queue<IntermideateDataForFacebookPost> dataReadyForImageGenerationQueue = new Queue<IntermideateDataForFacebookPost>();
        internal static Queue<IntermideateDataForFacebookPost> DataReadyForImageGenerationQueue
        {
            get
            {
                lock (dataReadyForImageGenerationQueue)
                {
                    return dataReadyForImageGenerationQueue;
                }
            }
        }

        static Queue<IntermideateDataForFacebookPost> dataReadyForFacebookEmailQueue = new Queue<IntermideateDataForFacebookPost>();
        internal static Queue<IntermideateDataForFacebookPost> DataReadyForFacebookEmailQueue
        {
            get
            {
                lock (dataReadyForFacebookEmailQueue)
                {
                    return dataReadyForFacebookEmailQueue;
                }
            }
        }

        bool isStopRequested = false;
        bool IsStopRequested
        {
            get
            {
                return isStopRequested;
            }
            set
            {
                isStopRequested = value;
            }
        }

        private void btnStopThreads_Click(object sender, EventArgs e)
        {
            IsStopRequested = true;
        }

        List<Thread> runningThreads = new List<Thread>();
        string tempFolderName = "C:\\TempFiles\\";


        public FrmPictureGenerator()
        {
            InitializeComponent();

            if (Directory.Exists(tempFolderName) == false)
            {
                Directory.CreateDirectory(tempFolderName);
            }


            //this.TopMost = true;
            webBrowser1.ScriptErrorsSuppressed = true;

            Thread t1 = new Thread(ProcessInputQueueAndPrepareHtmlContentToGenerateImage);
            t1.Start();
            //Thread t2 = new Thread(ProcessSendEmailToFacebookWithGeneratedPicture);
            Thread t2 = new Thread(ProcessFacebookPostingWithGeneratedPicture);
            t2.Start();

            

            runningThreads.Add(t1);
            runningThreads.Add(t2);
        }

        private void ProcessInputQueueAndPrepareHtmlContentToGenerateImage()
        {
            while (!IsStopRequested)
            {
                Thread.Sleep(1000);

                object obj = Defaults.FacebookPublishRequestQueue.Dequeue();

                if (obj == null)
                {
                    continue;
                }

                FaceBookEmailPostData facebookEmailPostInputData = (FaceBookEmailPostData)obj;

                if (facebookEmailPostInputData.FeedItem == null)
                {
                    TempLogger.Log("No valid feedItem in the facebook email posting data to generate picture." + Environment.NewLine + "The url is : " + facebookEmailPostInputData.FeedId);

                    continue;
                }

                if (facebookEmailPostInputData.SelectedFacebookPage==null)
                {
                    TempLogger.Log("No valid face book information is there to data to facebook.");
                    continue;
                }

                if (!string.IsNullOrEmpty(facebookEmailPostInputData.FeedItem.ImageUrl))
                {
                    try
                    {
                        var webClient = new WebClient();
                        byte[] imageBytes = webClient.DownloadData(facebookEmailPostInputData.FeedItem.ImageUrl);
                        facebookEmailPostInputData.ImageDataFromUrl = imageBytes;
                        facebookEmailPostInputData.IsImageDataSuccussfullyDownloaded = true;

                        facebookEmailPostInputData.FeedItem.ImageUrl = @"data:image/gif;base64," + Convert.ToBase64String(imageBytes);

                        Stream stream = new MemoryStream(imageBytes);
                       //Size size = new Size();

                        var size = ImageSizeHelper.GetDimensions(new BinaryReader(stream));

                        if (!size.IsEmpty)
                        {
                            facebookEmailPostInputData.ImageWidth = size.Width;
                            facebookEmailPostInputData.ImageHeight = size.Height;
                        }
                    }
                    catch (Exception ex)
                    {
                        TempLogger.Log("Error while downloading picture for facebook", ex);
                        facebookEmailPostInputData.IsImageDataSuccussfullyDownloaded = false;
                    }
                }

                string htmlFileContent = GetHtmlTemplateFromFile();

                htmlFileContent = ReplaceWithFeedItemValues(htmlFileContent, facebookEmailPostInputData.FeedItem);

                var intermideateDataForFacebookPost = new IntermideateDataForFacebookPost
                {
                    FaceBookEmailPostData = facebookEmailPostInputData,
                    HtmlContent = htmlFileContent
                };

                DataReadyForImageGenerationQueue.Enqueue(intermideateDataForFacebookPost);
            }
        }




        //bool isFacebookPublishingInProgress = false;

        //private void tmrInputQueueWatcher_Tick(object sender, EventArgs e)
        //{
        //    if (isFacebookPublishingInProgress == true)
        //        return;

        //    isFacebookPublishingInProgress = true;


        //    DisplayThreadState();

        //    if (DataReadyForImageGenerationQueue.Count == 0)
        //    {
        //        isFacebookPublishingInProgress = false;
        //        return;
        //    }


        //    var htmlContentToProcess = DataReadyForImageGenerationQueue.Dequeue();


        //    webBrowser1.DocumentText = htmlContentToProcess.HtmlContent;

        //    for (int i = 0; i < 1500; i++)
        //    {
        //        Application.DoEvents();
        //        Thread.Sleep(5);
        //    }

        //    Image img = webBrowser1.DrawToImage();

        //    var imageFilePath = "c:\\" + Guid.NewGuid().ToString("N") + "_browserImage.jpg";

        //    img.Save(imageFilePath);

        //    for (int i = 0; i < 100; i++)
        //    {
        //        Application.DoEvents();
        //        Thread.Sleep(5);
        //    }

        //    htmlContentToProcess.GeneratePicturePath = imageFilePath;

        //    DataReadyForFacebookEmailQueue.Enqueue(htmlContentToProcess);

        //    isFacebookPublishingInProgress = false;
        //}

        static bool isFacebookPublishingInProgress = false;

        private void tmrInputQueueWatcher_Tick(object sender, EventArgs e)
        {
            if (isFacebookPublishingInProgress == true)
                return;

            isFacebookPublishingInProgress = true;


            DisplayThreadState();

            if (DataReadyForImageGenerationQueue.Count == 0)
            {
                isFacebookPublishingInProgress = false;
                return;
            }


            var htmlContentToProcess = DataReadyForImageGenerationQueue.Dequeue();

            runningItem = htmlContentToProcess;

        
            string tempHtmlFile = Path.Combine(tempFolderName, Guid.NewGuid().ToString("N") + ".html");

            File.WriteAllText(tempHtmlFile, htmlContentToProcess.HtmlContent, Encoding.UTF8);

            runningItem.GeneratedHtmlFilePath = tempHtmlFile;


            int width = 600;
            int height = 500;

            WebBrowser browser = new WebBrowser();

            if (runningItem!=null && 
                runningItem.FaceBookEmailPostData != null && 
                runningItem.FaceBookEmailPostData.ImageWidth > 0 && 
                runningItem.FaceBookEmailPostData.ImageHeight > 0)
            {

                var widthRation = 500 / runningItem.FaceBookEmailPostData.ImageWidth;

                height = runningItem.FaceBookEmailPostData.ImageHeight * widthRation + 300;
            }
           

             

                if (width < runningItem.FaceBookEmailPostData.ImageWidth)
                {
                    width = runningItem.FaceBookEmailPostData.ImageWidth;
                }

                if (width > 800)
                {
                    width = 800;
                }

                browser.Width = width;
                browser.Height = height;

            browser.ScriptErrorsSuppressed = true;
            browser.ScrollBarsEnabled = false;
            browser.ScrollBarsEnabled = true;

            // This will be called when the page finishes loading
            browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);

            browser.Navigate(tempHtmlFile);

            // This prevents the application from exiting until
            // Application.Exit is called
            //Application.Run();






        }

        void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            OnDocumentCompleted(sender, e);
        }

        IntermideateDataForFacebookPost runningItem = null;

        void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (runningItem == null)
                return;

            var imageFilePath =  Path.Combine(tempFolderName, Guid.NewGuid().ToString("N") + "_browserImage.jpg");

            // Now that the page is loaded, save it to a bitmap
            WebBrowser browser = (WebBrowser)sender;

            var h = browser.Document.GetElementById("container").ClientRectangle.Height;
            var w = browser.Document.GetElementById("container").ClientRectangle.Width;

            browser.Height = h;
            browser.Width = w;

            using (Graphics graphics = browser.CreateGraphics())
            using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height, graphics))
            {
                Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                browser.DrawToBitmap(bitmap, bounds);

                bitmap.Save(imageFilePath, ImageFormat.Jpeg);
            }

            runningItem.GeneratePicturePath = imageFilePath;

            DataReadyForFacebookEmailQueue.Enqueue(runningItem);

          

            browser.Dispose();

            try
            {
                File.Delete(runningItem.GeneratedHtmlFilePath);
            }
            catch (Exception ex)
            {
                //todo: 
            }

            runningItem = null;

            isFacebookPublishingInProgress = false;

        }

        private void DisplayThreadState()
        {
            lblStatus.Text = "status:";

            lblStatus.Text = lblStatus.Text + Environment.NewLine + "Stop signal status :" + IsStopRequested.ToString();

            foreach (var t in runningThreads)
            {
                lblStatus.Text = lblStatus.Text + Environment.NewLine + t.Name + " : " + t.ThreadState.ToString();
            }
        }

        private void ProcessSendEmailToFacebookWithGeneratedPicture()
        {
            //return;

            while (!IsStopRequested)
            {

                Thread.Sleep(1000);

                if (DataReadyForFacebookEmailQueue.Count == 0)
                    continue;

                var tempData = DataReadyForFacebookEmailQueue.Dequeue();

                var feedItem = tempData.FaceBookEmailPostData.FeedItem;
                try
                {
                    var smtpUserToUse = FaceBookPageManager.GetNextGmailAddressToUseInSMTP();

                    if (smtpUserToUse == null)
                    {
                        throw new ApplicationException("There is no smtp user to send the mail. This is because there is no gmail is available.");
                    }

                    //Mail Message
                    using (MailMessage mM = new MailMessage())
                    {
                        //Mail Address
                        mM.From = new MailAddress(smtpUserToUse.GmailUserName);
                        //receiver email id
                        mM.To.Add(tempData.FaceBookEmailPostData.FaceBookSecretMailAddress);
                        //subject of the email
                        mM.Subject = "More details... " + feedItem.Link;
                        //deciding for the attachment
                        mM.Attachments.Add(new Attachment(tempData.GeneratePicturePath));
                        //add the body of the email
                        mM.Body = "facebook post";
                        mM.IsBodyHtml = true;
                        //SMTP client
                        using (SmtpClient sC = new SmtpClient("smtp.gmail.com"))
                        {
                            //port number for Gmail mail
                            sC.Port = 587;
                            //credentials to login in to Gmail account
                            sC.Credentials = new NetworkCredential(smtpUserToUse.GmailUserName, smtpUserToUse.GmailPassword);
                            //enabled SSL
                            sC.EnableSsl = true;
                            //Send an email

                            sC.Send(mM);
                        }
                    }


                }//end of try block
                catch (Exception ex)
                {
                    TempLogger.Log("Error while sending mail to facebook post", ex);
                }//end of catch
                finally
                {
                    File.Delete(tempData.GeneratePicturePath);
                }
            }
        }

        private void ProcessFacebookPostingWithGeneratedPicture()
        {
            //return;

            while (!IsStopRequested)
            {

                Thread.Sleep(1000);

                if (DataReadyForFacebookEmailQueue.Count == 0)
                    continue;

                var tempData = DataReadyForFacebookEmailQueue.Dequeue();

                var feedItem = tempData.FaceBookEmailPostData.FeedItem;

                if (tempData.FaceBookEmailPostData.SelectedFacebookPage==null || string.IsNullOrEmpty( tempData.FaceBookEmailPostData.SelectedFacebookPage.AccessToken) )
                {
                    TempLogger.Log("No valid selected facebook page is selected.");
                    continue;
                }

                //if (tempData.FaceBookEmailPostData.SelectedFacebookPage.TokenExpiryTime.AddHours(-1) > DateTime.UtcNow )
                //{
                //    TempLogger.Log("Facebook token is expired for the page." + tempData.FaceBookEmailPostData.SelectedFacebookPage.Name);
                //    continue;
                //}


                try
                {
                    //var smtpUserToUse = FaceBookPageManager.GetNextGmailAddressToUseInSMTP();

                    string feedLink = "http://www.lookatnews.com/go?id=" + feedItem.ID.ToString() + "&ref=fb";
                    
                    if (!KeyWordManager.IsDomainSupportsIframe(feedItem.Domain))
                    {
                        feedLink = feedLink + "&ni=y";
                    }

                    if (System.Configuration.ConfigurationSettings.AppSettings.Get("IsProduction") != null
                        && System.Configuration.ConfigurationSettings.AppSettings.Get("IsProduction") == "false")
                    {
                        feedLink = feedItem.Link;
                    }


                    Post_Picture(tempData.GeneratePicturePath,  feedItem.Title + "  More details... " + feedLink, tempData.FaceBookEmailPostData.SelectedFacebookPage.AccessToken, tempData.FaceBookEmailPostData.SelectedFacebookPage.Id);

                }//end of try block
                catch (Exception ex)
                {
                    TempLogger.Log("Error while calling to post facebook", ex);
                }//end of catch
                finally
                {
                    File.Delete(tempData.GeneratePicturePath);
                }
            }
        }

        #region Facebook posting related methods

        private bool Post_Picture(string Picture_Path, string Picture_Caption, string accessToken,string pageId)
        {

            //var doc = XDocument.Load("c:\\AccessToken.xml");
            var fb = new FacebookClient(accessToken);
            // new FacebookClient instance (AT: user access token or page access token)
            //var fb = new FacebookClient(AT);

            //string AlbumID = "";
            //if (!Is_User_Wall)
            //{
            //    // Find the 'Wall Photos' Album Object_ID
            //    // alter this part to publish photos to a different album
            //    var query = string.Format("SELECT object_id,name FROM album WHERE owner = me()");
            //    dynamic r1 = fb.Get("fql", new { q = query });
            //    foreach (var post in r1.data)
            //    {
            //        if (post.name == "Wall Photos") { AlbumID = Convert.ToString(post.object_id); }
            //    }

            //    if (AlbumID == "") { return false; }
            //}

            dynamic parameters = new ExpandoObject();
            parameters.message = Picture_Caption;
            //parameters.no_story = 0;
            // parameters.published = 0;

            parameters.source = new FacebookMediaObject
            {
                ContentType = "image/jpeg",
                FileName = Path.GetFileName(Picture_Path)
            }.SetValue(File.ReadAllBytes(Picture_Path));

            try
            {

                fb.Post(pageId + "/photos", parameters);

                //if (Is_User_Wall)
                //{
                //    // Post the image/picture to User wall
                //    fb.Post("me/photos", parameters);
                //    //fb.Post("me/feed", parameters);

                //    //fb.Post("636622736349107/feed", parameters);

                //    //fb.Post("702067566476045/photos", parameters);
                //}
                //else
                //{
                //    // Post the image/picture to the Page's Wall Photo album
                //    fb.Post("/" + AlbumID + "/photos", parameters);
                //}

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private bool Post_Message(string Message)
        {
            bool result = false;
            try
            {
                var doc = XDocument.Load("c:\\AccessToken.xml");
                var fb = new FacebookClient(doc.Root.Value);
                fb.Post("me/feed", new { message = Message + System.DateTime.Now.ToString(), link = "http://www.codeproject.com/KB/edit/DataEntryControl/image003.jpg" });
                //fb.Post("636622736349107/feed", new { message = Message + System.DateTime.Now.ToString(), link = "http://telugu.oneindia.in/news/2013/07/25/andhrapradesh-is-ys-jagan-changed-strategy-on-telangana-issue-119954.html" });
                //fb.Post("636622736349107/feed", new { message = Message + System.DateTime.Now.ToString() + " http://google.com/"});
                //636622736349107 , http://telugu.oneindia.in/news/2013/07/25/andhrapradesh-is-ys-jagan-changed-strategy-on-telangana-issue-119954.html
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
            }
            return result;

        }

        #endregion



        private string ReplaceWithFeedItemValues(string htmlFileContent, FeedItem feed)
        {
            if (feed == null)
            {
                StringBuilder sb = new StringBuilder(htmlFileContent);
                sb.Replace("{Title}", "తెలంగాణ: రేపు భేటీ, సోనియా ఆలోచన?తెలంగాణ: రేపు భేటీ, సోనియా ఆలోచన?తెలంగాణ: రేపు భేటీ, సోనియా ఆలోచన?తెలంగాణ: రేపు భేటీ, సోనియా ఆలోచన?");
                sb.Replace("{ImageUrl}", "http://telugu.oneindia.in/img/2013/07/12-sonia-telangana-600.jpg");
                sb.Replace("{domain}", "gujarati.oneindia.in");

                return sb.ToString();
            }
            else
            {
                StringBuilder sb = new StringBuilder(htmlFileContent);
                sb.Replace("{Title}", feed.Title);
                sb.Replace("{ImageUrl}", feed.ImageUrl);
                sb.Replace("{domain}", feed.Domain);

                if (!string.IsNullOrEmpty(feed.ImageUrl))
                    sb.Replace("{imgheight}", "auto");
                else
                    sb.Replace("{imgheight}", "0px");


                return sb.ToString();
            }
        }


        static string htmlFileContent = null;
        private static string GetHtmlTemplateFromFile()
        {
            if (string.IsNullOrEmpty(htmlFileContent))
                htmlFileContent = File.ReadAllText(Path.Combine(Environment.CurrentDirectory, "template.html"));
            return htmlFileContent;
        }

        #region testing purpose

        private void btnPostToFacebook_Click(object sender, EventArgs e)
        {
            //test the image size stuff.
            
            GetSizeOfRemoteImage();

            return; 


            var webClient = new WebClient();
            byte[] imageBytes = webClient.DownloadData("http://www.codeproject.com/KB/edit/DataEntryControl/image001.png");
            //facebookEmailPostInputData.ImageDataFromUrl = imageBytes;
            //facebookEmailPostInputData.IsImageDataSuccussfullyDownloaded = true;

           // facebookEmailPostInputData.FeedItem.ImageUrl = @"data:image/gif;base64," + Convert.ToBase64String(imageBytes);

            Stream stream = new MemoryStream(imageBytes);
           

           var size = ImageSizeHelper.GetDimensions(new BinaryReader(stream));


            //webBrowser1.DocumentText = "<h1>welcome</h1>";

            string htmlFileContent = File.ReadAllText(Path.Combine(Environment.CurrentDirectory, "template.html"));

            htmlFileContent = ReplaceWithFeedItemValues(htmlFileContent, null);

            webBrowser1.DocumentText = htmlFileContent;

            for (int i = 0; i < 1000; i++)
            {
                Application.DoEvents();
                Thread.Sleep(5);
            }

            Image img = webBrowser1.DrawToImage();

            var imageFilePath = "c:\\" + DateTime.Now.Ticks.ToString() + "_browserImage.jpg";

            img.Save(imageFilePath);




            return;


        }

        private void GetSizeOfRemoteImage()
        {
            string urlPath = "http://telugu.oneindia.in/img/2013/08/28-ashok-babu-600.jpg";

           // System.Drawing.Image img = System.Drawing.Image.FromStream(null);

            HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create(urlPath);

                // returned values are returned as a stream, then read into a string
                String lsResponse = string.Empty;
                using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse())
                {

                    System.Drawing.Image image = System.Drawing.Image.FromStream(lxResponse.GetResponseStream());

                    
                }


        }

        #endregion


    }
}
